package com.yb.bluetooth.normal

import android.annotation.SuppressLint
import android.app.Activity
import android.bluetooth.BluetoothAdapter
import android.bluetooth.BluetoothDevice
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import androidx.fragment.app.FragmentActivity
import com.yb.bluetooth.util.ActivityCallUtils
import timber.log.Timber
import java.util.*

/**
 * Created by zyb
 * Date 2021/11/16 16:16
 * Desc 传统蓝牙工具类
 */

@SuppressLint("StaticFieldLeak")
object BtUtils {

    private lateinit var mContext: Context
    private var mBluetoothDiscoverableListener: ((Boolean) -> Unit)? = null
    private var mBluetoothChangeListener: ((Boolean) -> Unit)? = null
    private var mScanDeviceCallback: ((BluetoothDevice?) -> Unit)? = null
    private const val REQUEST_ENABLE_BT = 0x1
    private const val REQUEST_ENABLE_DISCOVERABLE = 0x2
    const val TAG = "Bluetooth"
    val mBluetoothAdapter: BluetoothAdapter? by lazy(LazyThreadSafetyMode.NONE){
        BluetoothAdapter.getDefaultAdapter()
    }

    /**
     *  初始化
     *
     * @param context 上下文
     * @param uuid 标识
     */
    fun init(context: Context, uuid: UUID) {
        mContext = context.applicationContext
        BtService.init(uuid)
    }

    /**
     * 设备是否支持蓝牙
     */
    fun isSupportBluetooth(): Boolean {
        return mBluetoothAdapter != null
    }

    /**
     * 打开蓝牙
     *
     * @param activity
     * @param callback 结果回调
     */
    fun openBluetooth(activity: FragmentActivity, callback: ((Boolean) -> Unit)? = null) {
        if (!isEnabled()) {
            val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            if (callback != null) {
                ActivityCallUtils.instance(activity).apply {
                    callActivityResult(REQUEST_ENABLE_BT) { resultCode, data ->
                        callback.invoke(isEnabled())
                    }
                    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
                }
            } else {
                activity.startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT)
            }
        } else {
            Timber.tag(TAG).d("蓝牙已开启")
        }
    }

    /**
     * 关闭蓝牙
     */
    fun closeBluetooth(): Boolean? {
        return mBluetoothAdapter?.disable()
    }

    /**
     * 蓝牙是否打开
     */
    fun isEnabled(): Boolean {
        return mBluetoothAdapter?.isEnabled == true
    }

    /**
     * 注册蓝牙更改监听器
     *
     * @param listener 监听
     */
    fun registerBluetoothChangeListener(listener: (Boolean) -> Unit) {
        mBluetoothChangeListener = listener
        val filter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)
        mContext.registerReceiver(mBluetoothChangeReceiver, filter)
    }

    /**
     * 注销蓝牙更改监听器
     */
    fun unregisterBluetoothChangeListener() {
        mContext.unregisterReceiver(mBluetoothChangeReceiver)
    }

    /**
     * 获取已配对设备
     */
    fun getPairedDevices(): MutableSet<BluetoothDevice>? {
        return mBluetoothAdapter?.bondedDevices
    }

    /**
     * 扫描/发现设备
     *
     * 发现进程通常包含约 12 秒钟的查询扫描
     * 随后会对发现的每台设备进行页面扫描，以检索其蓝牙名称
     * Android 6.0后扫描需要开启定位信息
     *
     * @param callback 结果回调
     */
    fun scanDevice(callback: (BluetoothDevice?) -> Unit) {
        mScanDeviceCallback = callback
        cancelScanDevice()
        if (mBluetoothAdapter?.startDiscovery() == true) {
            val filter = IntentFilter(BluetoothDevice.ACTION_FOUND)
            mContext.registerReceiver(mScanDeviceReceiver, filter)
        } else {
            Timber.tag(TAG).d("开启扫描设备失败")
        }
    }

    /**
     * 停止扫描/发现设备
     */
    fun cancelScanDevice() {
        try {
            if (mBluetoothAdapter?.isDiscovering == true) {
                mBluetoothAdapter?.cancelDiscovery()
                mContext.unregisterReceiver(mScanDeviceReceiver)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 启用可检测性(可被其他设备发现)
     *
     * 默认情况下，设备处于可检测到模式的时间为 120 秒（2 分钟）
     * 启用可检测性可自动启用蓝牙
     * 用户拒绝或出现错误，onActivityResult()回调为RESULT_CANCELED
     * 将 EXTRA_DISCOVERABLE_DURATION Extra 属性的值设置为 0，则设备将始终处于可检测到模式。此配置安全性低，非常不建议使用。
     *
     * @param activity
     * @param time 可检测时间 最高可为3600秒(一小时)
     * @param callback 开启结果回调
     */
    fun enableDiscoverable(activity: FragmentActivity,
                           time: Int? = null,
                           callback: ((Boolean) -> Unit)? = null) {
        if (mBluetoothAdapter?.isDiscovering == true) return
        val discoverableIntent = Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE)
        time?.let {
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, it)
        }
        if (callback != null) {
            ActivityCallUtils.instance(activity).apply {
                callActivityResult(REQUEST_ENABLE_DISCOVERABLE) { resultCode, data ->
                    callback.invoke(resultCode!= Activity.RESULT_CANCELED)
                }
                startActivityForResult(discoverableIntent, REQUEST_ENABLE_DISCOVERABLE)
            }
        } else {
            activity.startActivityForResult(discoverableIntent, REQUEST_ENABLE_DISCOVERABLE)
        }

    }

    /**
     * 根据mac地址获取远程设备
     *
     * @param mac 设备的mac地址
     */
    fun getRemoteDevice(mac: String): BluetoothDevice? {
        return mBluetoothAdapter?.getRemoteDevice(mac)
    }

    /**
     * 注册蓝牙可检测性监听器
     *
     * @param listener 结果回调
     */
    fun registerBluetoothDiscoverableListener(listener: (Boolean) -> Unit) {
        mBluetoothDiscoverableListener = listener
        val filter = IntentFilter(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED)
        mContext.registerReceiver(mBluetoothDiscoverableReceiver, filter)
    }

    /**
     * 注销蓝牙可检测性监听器
     */
    fun unregisterBluetoothDiscoverableListener() {
        mContext.unregisterReceiver(mBluetoothDiscoverableReceiver)
    }


    /**
     * 启动接受连接
     *
     * @param keep 是否保持接收
     */
    fun startAccept(name:String, keep: Boolean = false) {
        BtService.start(name, keep)
    }

    /**
     * 关闭接受连接
     */
    fun closeAccept() {
        BtService.close()
    }


    /**
     * 发送消息
     *
     * @param address 设备的mac地址
     * @param message  消息
     */
    fun sendMessage(address: String, message: String, callback: ((Boolean) -> Unit)? = null) {
        BtService.send(address, message.toByteArray(), callback)
    }


    /**
     * 连接蓝牙设备
     *
     * @param address 设备的mac地址
     */
    fun connectDevice(address: String) {
        if (isConnected(address)) return Timber.tag(TAG).d("获取蓝牙设备 $address 已连接")
        val device = getRemoteDevice(address)
        if (device == null) return Timber.tag(TAG).d("获取蓝牙设备 $device 失败")
        BtService.connect(device)
    }

    /**
     *  断开连接的蓝牙设备
     *
     *  @param address 设备的mac地址
     */
    fun disconnectDevice(address: String) {
        if (!isConnected(address)) return Timber.tag(TAG).d("获取蓝牙设备 $address 已断开")
        BtService.disconnect(address)
    }

    /**
     * 指定设备是否连接
     *
     * @param address 设备的mac地址
     * @return
     */
    fun isConnected(address: String): Boolean {
        return BtService.isConnected(address)
    }

    /**
     * 蓝牙服务监听
     *
     * @param state 状态监听
     * @param receive 接收监听
     */
    fun setBtListener(state: ((BluetoothDevice, BtAction, Exception?) -> Unit)? = null,
                      receive: ((BluetoothDevice, String) -> Unit)? = null) {
        BtService.setBtListener(state, receive)
    }


    private val mBluetoothDiscoverableReceiver = object : BroadcastReceiver() {

        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent?.action == BluetoothAdapter.ACTION_SCAN_MODE_CHANGED) {
                when (intent.getIntExtra(BluetoothAdapter.EXTRA_SCAN_MODE, 0)) {
                    BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE -> {
                        Timber.tag(TAG).d("设备处于可检测到模式")
                        mBluetoothChangeListener?.invoke(true)
                    }
                    BluetoothAdapter.SCAN_MODE_CONNECTABLE -> {
                        Timber.tag(TAG).d("设备未处于可检测到模式，但仍能收到连接")
                    }
                    BluetoothAdapter.SCAN_MODE_NONE -> {
                        Timber.tag(TAG).d("设备未处于可检测到模式，且无法收到连接")
                        mBluetoothChangeListener?.invoke(false)
                    }
                }
            }
        }
    }

    private val mBluetoothChangeReceiver = object : BroadcastReceiver() {

        override fun onReceive(context: Context?, intent: Intent?) {
            if (intent?.action == BluetoothAdapter.ACTION_STATE_CHANGED) {
                when (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0)) {
                    BluetoothAdapter.STATE_TURNING_ON -> {
                        Timber.tag(TAG).d("蓝牙正在打开")
                    }
                    BluetoothAdapter.STATE_TURNING_OFF -> {
                        Timber.tag(TAG).d("蓝牙正在关闭")
                    }
                    BluetoothAdapter.STATE_ON -> {
                        Timber.tag(TAG).d("蓝牙已开启")
                        mBluetoothChangeListener?.invoke(true)
                    }
                    BluetoothAdapter.STATE_OFF -> {
                        Timber.tag(TAG).d("蓝牙已关闭")
                        mBluetoothChangeListener?.invoke(false)
                    }
                }
            }
        }
    }

    private val mScanDeviceReceiver = object : BroadcastReceiver() {

        override fun onReceive(context: Context, intent: Intent?) {
            if (intent?.action == BluetoothDevice.ACTION_FOUND) {
                val device: BluetoothDevice? =
                    intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)
                if (device?.bondState != BluetoothDevice.BOND_BONDED)
                    mScanDeviceCallback?.invoke(device)
            }
        }
    }

}